package com.zh.yqbj.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.yqbj.constant.FileConstant;
import com.zh.yqbj.entity.UFile;
import com.zh.yqbj.entity.UserFile;
import com.zh.yqbj.mapper.UFileMapper;
import com.zh.yqbj.service.UFileService;
import com.zh.yqbj.service.UserFileService;
import com.zh.yqbj.util.FileSizeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 用户文件表 服务实现类
 * </p>
 *
 * @author zh
 * @since 2024-04-05 11:21:12
 */
@Service
@Slf4j
public class UFileServiceImpl extends ServiceImpl<UFileMapper, UFile> implements UFileService {
    @Value("${spring.servlet.multipart.location}")
    private String filePath;
    private String userId = "common";
    private String dirPrefix = filePath + userId + "/";

    @Value("${file.baseUrl}")
    private String mappingPath;
    private static final String IMAGE_DIR_SUFFIX = "image/";
    private static final String OTHER_DIR_SUFFIX = "other/";
    private static final List<String> IMAGE_EXTENSIONS = List.of(".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff",
            ".tif", ".webp", ".svg", ".ico", ".psd", ".ai");

    @Autowired
    private UserFileService userFileService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<String> fileUpload(MultipartFile[] files) throws IOException {
        // 所属人
        boolean isLogin = StpUtil.isLogin();
        if (isLogin) {
            userId = StpUtil.getLoginIdAsString();
            dirPrefix = filePath + userId + "/";
        }
        List<String> uploadFiles = new ArrayList<>();
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();
            assert fileName != null;
            String head = fileName.substring(0, fileName.lastIndexOf("."));
            String tail = fileName.substring(fileName.lastIndexOf("."));
            // 本名+时间+后缀
            String newFileName = head +
                    "-" +
                    LocalDateTimeUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS") +
                    tail;
            // 第二次坑了。不要用this，事务会失效
            UFileService uFileService = (UFileService) AopContext.currentProxy();
            if (IMAGE_EXTENSIONS.contains(tail)) {
                String uploadFile = uFileService.imageUpload(dirPrefix, file, newFileName);
                uploadFiles.add(uploadFile);
            }
        }
        return uploadFiles;
    }

    @Override
    public String imageUpload(String dirPrefix, MultipartFile file, String newFileName) throws IOException {
        dirPrefix += IMAGE_DIR_SUFFIX;
        UFileService uFileService = (UFileService) AopContext.currentProxy();
        //1. 查这个父文件夹是否存在，不存在则创建
        UFile imageRoot = uFileService.getOne(new LambdaQueryWrapper<UFile>().eq(UFile::getFilePath, dirPrefix));
        File userDir = new File(dirPrefix);
        if (imageRoot == null || !userDir.exists()) {  // 如果文件夹不存在，则创建文件夹
            imageRoot = new UFile();
            userDir.mkdirs();
            imageRoot.setParentId("0");
            imageRoot.setFilename(userId+"的图片文件夹");
            imageRoot.setFilePath(dirPrefix);
            imageRoot.setFileComment(userId + "的图片文件夹");
            imageRoot.setType(FileConstant.TYPE_FLOAD);
            uFileService.save(imageRoot);
            UserFile userFile = new UserFile();
            userFile.setUserId(userId);
            userFile.setFileId(imageRoot.getId());
            userFile.setCreateTime(LocalDateTimeUtil.now());
            userFile.setUpdateTime(LocalDateTimeUtil.now());
            userFileService.save(userFile);
        }
        File dest = new File(userDir, newFileName);
        // 转存文件
        file.transferTo(dest);
        //返回文件上传后的地址
        log.info(userId + "上传了文件:" + newFileName);
        log.info("上传成功，当前上传的文件保存在 {}", dest.getPath());
        String targetPath = dest.getPath().replace(filePath, mappingPath);
        log.info("当前文件访问路径:{}", targetPath);
        // 把文件上传后的地址保存到数据库
        //TODO 把文件信息存入mysql
        uFileService.transferToDB(imageRoot.getId(), dest, targetPath);
        return targetPath;
    }

    @Override
    public void transferToDB(String pid, File file, String fileUrl) {
        //1. 存文件表
        UFileService uFileService = (UFileService) AopContext.currentProxy();
        UFile uFile = new UFile();
        uFile.setParentId(pid);
        uFile.setFilename(file.getName());
        uFile.setFilePath(fileUrl);
        uFile.setType(FileConstant.TYPE_FILE);
        uFile.setFileSize(FileSizeUtil.getFileSize(file));
        uFile.setFileComment("图片");
        uFileService.save(uFile);
        //2. 更新父文件夹大小
        UFile father = uFileService.getById(pid);
        File fatherFile = new File(father.getFilePath());
        String fatherSize = FileSizeUtil.getFileSize(fatherFile);
        father.setFileSize(fatherSize);
        uFileService.updateById(father);
        //3. 存映射表
        UserFile userFile = new UserFile();
        userFile.setUserId(userId);
        userFile.setFileId(uFile.getId());
        userFile.setCreateTime(LocalDateTimeUtil.now());
        userFile.setUpdateTime(LocalDateTimeUtil.now());
        userFileService.save(userFile);
    }
}
